﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Threading;

namespace Workbench.Presentation
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        private object timersLock = new object();
        private Dictionary<string, DispatcherTimer> timers;
        protected Dictionary<string, DispatcherTimer> Timers
        {
            get 
            {
                if(timers == null)
                {
                    lock (timersLock)
                    {
                        if (timers == null)
                        {
                            timers = new Dictionary<string, DispatcherTimer>();
                        }
                    }
                }
                return timers;
            }
        }
        protected void RaiseThrottledPropertyChanged(int delayMs, [CallerMemberName]string propertyName = "")
        {
            if (PropertyChanged == null) return;

            DispatcherTimer timer;
            if(!Timers.TryGetValue(propertyName, out timer))
            {
                timer = new DispatcherTimer();
                timers.Add(propertyName, timer);
                timer.Interval = TimeSpan.FromMilliseconds(delayMs);
                timer.Tick += timer_Tick;
                timer.Tag = propertyName;
                timer.Start();
            }
            else
            {
                if(timer.IsEnabled) timer.Stop();
                timer.Start();
            }
        }

        void timer_Tick(object sender, System.EventArgs e)
        {
 	        var timer = sender as DispatcherTimer;
            timer.Stop();
            RaisePropertyChanged((string)timer.Tag);
        }
    }

    public abstract class TabViewModelBase : ViewModelBase
    {
        public TabViewModelBase(string header)
        {
            Header = header;
            PropertyChanged += TabViewModelBase_PropertyChanged;
        }

        void TabViewModelBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsSelected":
                    if (IsEnabled)
                    {
                        if (IsSelected)
                        {
                            IsLoading = true;
                            Load();
                            IsLoading = false;
                        }
                        else Unload();
                    }
                    else Unload();
                    break;
                case "IsEnabled":
                    if (IsEnabled)
                    {
                        if (IsSelected)
                        {
                            IsLoading = true;
                            Load();
                            IsLoading = false;
                        }
                        else Unload();
                    }
                    else Unload();
                    break;
            }
        }

        private string header;
        public string Header
        {
            get { return header; }
            set { header = value; RaisePropertyChanged(); }
        }

        private bool isSelected;
        public bool IsSelected
        {
            get { return isSelected; }
            set { isSelected = value; RaisePropertyChanged(); }
        }

        private bool isEnabled;
        public bool IsEnabled
        {
            get { return isEnabled; }
            set { isEnabled = value; RaisePropertyChanged(); }
        }

        private bool isLoading;
        public bool IsLoading
        {
            get { return isLoading; }
            set { isLoading = value; RaisePropertyChanged(); }
        }

        public abstract void Load();
        public abstract void Unload();

        public event Action<string> Error;
        public void RaiseError(string message)
        {
            if (Error != null) Error(message);
        }
    }
}
